package cn.dengta.webapp.trade.service;

import java.math.BigDecimal;
import java.util.*;
import java.util.concurrent.TimeUnit;
import javax.annotation.Resource;

import cn.dengta.common.model.TimeInterval;
import cn.dengta.common.util.Formats;
import cn.dengta.context.model.RedisKey;
import cn.dengta.context.model.WesKit;
import cn.dengta.webapp.base.service.BaseServiceImpl;
import cn.dengta.webapp.base.util.MybatisUtil;
import cn.dengta.webapp.trade.dao.GoddessWeekLogDao;
import cn.dengta.webapp.trade.dto.UserIntegralIncomeDTO;
import cn.dengta.webapp.trade.entity.Meta;
import cn.dengta.webapp.trade.model.GoddessWeekLog;
import cn.dengta.webapp.trade.model.GoddessWeekType;
import cn.dengta.webapp.user.model.Gender;
import cn.dengta.webapp.user.model.MetaType;
import cn.dengta.webapp.user.service.RemoteTaskAccountService;
import com.baomidou.mybatisplus.core.conditions.query.QueryWrapper;
import com.baomidou.mybatisplus.core.toolkit.Wrappers;
import lombok.Getter;
import lombok.extern.slf4j.Slf4j;
import me.codeplayer.util.EasyDate;
import me.codeplayer.util.X;
import org.springframework.beans.factory.annotation.Value;
import org.springframework.data.redis.core.StringRedisTemplate;
import org.springframework.stereotype.Service;

/**
 * 女神权益发放表 服务实现类
 *
 * @author lizhichao
 * @since 2024-08-08
 */
@Service
@Slf4j
public class GoddessWeekLogService extends BaseServiceImpl<GoddessWeekLog, GoddessWeekLogDao, Long> {

	@Resource
	UserIntegralLogService userIntegralLogService;

	@Resource
	MetaService metaService;

	@Resource
	StringRedisTemplate stringRedisTemplate;

	@Getter
	@Value("${goddess.integral.limit:500}")
	BigDecimal integralLimit;

	@Resource
	RemoteTaskAccountService remoteTaskAccountService;

	public BigDecimal getTotalIncome(Long userId, TimeInterval interval) {
		final UserIntegralIncomeDTO userIntegralIncomeDTO = userIntegralLogService.sumUserIncomeIntegralByInterval(userId, interval);
		return X.map(userIntegralIncomeDTO, dto -> dto.getChatIncome().add(dto.getGiftTotalIncome()).add(dto.getMediaTotalIncome()));
	}

	public boolean save(Long userId, long now,GoddessWeekType weekType, WesKit wesKit) {
		Integer freeNum = getFreeNum(wesKit);
		if (getCurrentMonthByType(userId, now, weekType) != null) {
			return true;
		}
		final GoddessWeekLog goddessWeekLog = new GoddessWeekLog();
		final GoddessWeekLog last = getLastLog(userId);
		int remainDays = last == null ? 0 : new EasyDate(last.getEndTime()).getDay() - new EasyDate(now).getDay();
		final TimeInterval rewardInterval = GoddessWeekType.calc(now, remainDays);
		goddessWeekLog.setType(weekType.getValue());
		goddessWeekLog.setBeginTime(rewardInterval.getBegin());
		goddessWeekLog.setEndTime(rewardInterval.getEnd());
		goddessWeekLog.initTime(new Date(now));
		goddessWeekLog.setUserId(userId);
		goddessWeekLog.setFreeNum(freeNum);
		save(goddessWeekLog);
		log.info("【女神权益】{} 达标 {}", userId, Formats.formatDefDate(rewardInterval.getBegin()));
		final String hotsKey = RedisKey.getGoddessHasHots(userId);
		stringRedisTemplate.delete(hotsKey);

		final String goddessHasMedal = RedisKey.getGoddessHasMedal(userId);

		String has = stringRedisTemplate.opsForValue().get(goddessHasMedal);
		if (!"1".equals(has)) {
			final List<GoddessWeekLog> logs = findByMonth(userId, now);
			boolean r = logs.size() == 4;
			if (r) {
				stringRedisTemplate.opsForValue().set(goddessHasMedal, "1");
			}
		}
		return true;
	}

	public Integer getFreeNum(WesKit wesKit) {
		Integer freeNum;
		final Meta type = metaService.findSingleCacheByTypeAndWeskit(MetaType.femaleFreeGreet, wesKit);
		if (type == null) {
			freeNum = 0;
		} else {
			final MetaType.FemaleFreeGreet value = (MetaType.FemaleFreeGreet) type.findTypeValueConfig();
			freeNum = value.getGoddessFreeNum();
		}
		return freeNum;
	}

	public GoddessWeekLog getCurrentMonthByType(Long userId, long now, GoddessWeekType weekType) {
		Date begin = EasyDate.beginOf(new Date(now), Calendar.MONTH);
		Date end = EasyDate.endOf(new Date(now), Calendar.MONTH);
		TimeInterval interval = new TimeInterval(begin, end);
		return selectOne(popWrapper(userId, interval, weekType));
	}

	public List<GoddessWeekLog> findByMonth(Long userId, long now) {
		Date begin = EasyDate.beginOf(new Date(now), Calendar.MONTH);
		Date end = EasyDate.endOf(new Date(now), Calendar.MONTH);
		TimeInterval interval = new TimeInterval(begin, end);
		final QueryWrapper<GoddessWeekLog> queryWrapper = popWrapper(userId, interval, null);
		queryWrapper.orderByAsc(GoddessWeekLog.TYPE);
		return selectList(queryWrapper);
	}

	public boolean hasMedal(Long userId, long now) {
		final String key = RedisKey.getGoddessHasMedal(userId);
		String has = stringRedisTemplate.opsForValue().get(key);
		if (has != null) {
			return "1".equals(has);
		}
		final EasyDate lastMonth = new EasyDate(now);
		List<GoddessWeekLog> logs = findByMonth(userId, lastMonth.getTime());
		boolean r = logs.size() == 4;
		if (!r) {
			lastMonth.addMonth(-1);
			logs = findByMonth(userId, lastMonth.getTime());
			r = logs.size() == 4;
		}
		has = r ? "1" : "0";
		if (r) {
			stringRedisTemplate.opsForValue().set(key, has);
		} else {
			stringRedisTemplate.opsForValue().set(key, has, 5, TimeUnit.MINUTES);
		}
		return r;
	}

	public boolean hasHot(Long userId, long now) {
		final String key = RedisKey.getGoddessHasHots(userId);
		String has = stringRedisTemplate.opsForValue().get(key);
		if (has != null) {
			return "1".equals(has);
		}
		final List<GoddessWeekLog> logs = findByMonth(userId, now);
		boolean ret = false;
		Date end = EasyDate.endOf(new Date(now), Calendar.DAY_OF_MONTH);
		if (X.isValid(logs)) {
			GoddessWeekLog lastLog = logs.get(logs.size() - 1);
			ret = lastLog.getEndTime().getTime() > now;
			end = lastLog.getEndTime();
		}
		has = ret ? "1" : "0";
		stringRedisTemplate.opsForValue().set(key, has, 1, TimeUnit.MINUTES);
		return ret;
	}

	public GoddessWeekLog getLastLog(Long userId) {
		final Date date = new Date(System.currentTimeMillis());
		final QueryWrapper<GoddessWeekLog> wrapper = Wrappers.query();
		wrapper.eq(GoddessWeekLog.USER_ID, userId);
		wrapper.le(GoddessWeekLog.BEGIN_TIME, date);
		wrapper.ge(GoddessWeekLog.END_TIME, date);
		wrapper.orderByDesc(GoddessWeekLog.BEGIN_TIME);
		wrapper.last("limit 1");
		return selectOne(wrapper);
	}

	public QueryWrapper<GoddessWeekLog> popWrapper(Long userId, TimeInterval beginInterval, GoddessWeekType weekType) {
		final QueryWrapper<GoddessWeekLog> wrapper = Wrappers.query();
		wrapper.eq(GoddessWeekLog.USER_ID, userId);
		if (weekType != null) {
			wrapper.eq(GoddessWeekLog.TYPE, weekType.getValue());
		}
		if (beginInterval != null) {
			MybatisUtil.wrapperInterval(wrapper, GoddessWeekLog.BEGIN_TIME, beginInterval);
		}
		return wrapper;
	}

	public boolean isTaskCompleted(Long userId, WesKit wesKit, Gender gender) {
		final String key = RedisKey.getGoddessTaskCompleted(userId);
		if (Boolean.TRUE.equals(stringRedisTemplate.hasKey(key))) {
			return true;
		}
		final boolean completed = remoteTaskAccountService.isGoddessTaskCompleted(userId, wesKit, gender);
		if (completed) {
			stringRedisTemplate.opsForValue().set(key, "1", 60, TimeUnit.MINUTES);
		}
		return completed;
	}

}
